package com.batchengine.util;

import com.batchengine.service.Service;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created by sunil.incubator@yahoo.com.
 * User: sunil.kalva
 * Date: Jul 11, 2009
 */
public class SocketListener extends Listener {

    /**
     * Fully qualified class name
     */
    private static final String FQCN = SocketListener.class.getName();

    /**
     * Only used for logging
     */
    protected int port;
    protected String password;

    protected ServerSocket serverSocket;
    private volatile boolean needsToStop = false;

    /**
     * Creates a <tt>SocketListener</tt> for a service and its corresponding port. This constructor does not start the
     * thread.
     *
     * @param service the service
     * @param port    the service's port
     * @throws java.io.IOException if an I/O error occurs when creating the server socket
     */
    public SocketListener(Service service, int port) throws IOException {
        this(service, port, null);
    }

    /**
     * Creates a <tt>SocketListener</tt> for a service that requires password authentication and its corresponding port.
     * This constructor does not start the thread.
     *
     * @param service  the service
     * @param port     the service's port
     * @param password the password
     * @throws java.io.IOException if an I/O error occurs when creating the server socket
     */
    public SocketListener(Service service, int port, String password) throws IOException {
        super(service);
        this.port = port;
        this.password = password;
        serverSocket = new ServerSocket(port);
    }

    /**
     * This method loops and listens for conneciton on the server socket. It will return when another thread calls
     * this object's <tt>pleaseStop</tt> method.
     */
    public void run() {
        initService();
        while (!needsToStop) {
            try {
                Socket socket = serverSocket.accept();

                ConnectionHandler connectionHandler = new ConnectionHandler(socket, service, password);
                connectionHandler.start();
            } catch (InterruptedIOException e) {
                // Can ingore. The thread is interrupted by the pleaseStop() method.
            } catch (IOException ioe) {
            }
        }
    }

    /**
     * Interrupts the listener thread and asks it to stop.
     */
    public void pleaseStop() {
        needsToStop = true;
        this.interrupt();
        try {
            serverSocket.close();
        } catch (IOException ioe) {
            // Ignore exception when closing socket.
        }
    }

}
